<template>
  <div class="throttle-demo">
    <!-- 使用节流功能的按钮 -->
    <button @click="throttledClick">点击我 (节流)</button>
    <!-- 显示点击计数 -->
    <p>点击次数: {{ clickCount }}</p>
    <!-- 显示实际触发次数 -->
    <p>实际触发次数: {{ actualTriggerCount }}</p>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';

// 点击计数器
const clickCount = ref(0);
// 实际触发次数计数器
const actualTriggerCount = ref(0);

// 节流函数
const throttle = <T extends (...args: any[]) => any>(
  func: T,
  delay: number
): ((...args: Parameters<T>) => void) => {
  let lastExecTime = 0;
  let timeoutId: ReturnType<typeof setTimeout> | null = null;

  return (...args: Parameters<T>) => {
    const now = Date.now();
    const elapsed = now - lastExecTime;
    const remaining = delay - elapsed;

    // 清除待处理的执行
    if (timeoutId) {
      clearTimeout(timeoutId);
      timeoutId = null;
    }

    // 如果距离上次执行已超过延迟时间，立即执行
    if (remaining <= 0) {
      lastExecTime = now;
      func(...args);
    } 
    // 否则设置定时器在剩余时间后执行
    else {
      timeoutId = setTimeout(() => {
        lastExecTime = Date.now();
        func(...args);
      }, remaining);
    }
  };
};

// 实际要执行的函数
const handleClick = () => {
  actualTriggerCount.value++;
  console.log('实际触发:', actualTriggerCount.value);
};

// 创建节流版本的处理函数 (500ms内只能触发一次)
const throttledClick = throttle(handleClick, 500);

// 处理按钮点击 (每次点击都会计数)
const handleButtonClick = () => {
  clickCount.value++;
  throttledClick(); // 调用节流函数
};
</script>

<style lang="less" scoped>
.throttle-demo {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 200px;
  padding: 20px;
  font-family: Arial, sans-serif;
  
  button {
    padding: 12px 24px;
    font-size: 16px;
    background-color: #3498db;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.3s;
    margin-bottom: 20px;

    &:hover {
      background-color: #2980b9;
    }

    &:active {
      transform: scale(0.98);
    }
  }

  p {
    font-size: 18px;
    margin: 8px 0;
  }
}
</style>